﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

public class LifeCycle
{
    public const int defaultFPS = 30;
    protected int m_FPS = defaultFPS;
    protected long ticksPerFrame => 10000000 / m_FPS+1;

    List<IGameLifeCycle> m_ToAddLifeCycles = new List<IGameLifeCycle>();
    List<IGameLifeCycle> m_ToRemoveLifeCycles = new List<IGameLifeCycle>();
    protected List<IGameLifeCycle> m_GameLifeCycles = new List<IGameLifeCycle>();

    public virtual void Start(int fps)
    {
        m_FPS = fps;

        GameDebug.Log($"LifeCycle  Start:{fps}");
        
        Thread updateThread = new Thread(Update);
        updateThread.Start();
    }

    protected long m_StartTime = -1;

    protected int m_CurUpdateTimes;

   // protected int m_TrueUpdateTimes;

    public int curFrame => m_CurUpdateTimes;

    public void AddLifeCycle(IGameLifeCycle lifeCycle)
    {
        lock (m_ToAddLifeCycles)
        {
            m_ToAddLifeCycles.Add(lifeCycle);
        }
    }

    public void RemoveLifeCycle(IGameLifeCycle lifeCycle)
    {
        lock (m_ToRemoveLifeCycles)
        {
            m_ToRemoveLifeCycles.Add(lifeCycle);
        }
    }

    void Update()
    {
        while (true)
        {
            Thread.Sleep(2);

            if (m_StartTime == -1)
            {
                m_StartTime = CommonFunctions.GetTimeStamp();
            }

            long curTime = CommonFunctions.GetTimeStamp();

            //GameDebug.Log($"curTime：{curTime}  pass:{curTime - m_StartTime} trueUpdateTimes:{trueUpdateTimes}");
            int curUpdateTimes = (int)((curTime - m_StartTime) / ticksPerFrame);

            if (m_CurUpdateTimes == curUpdateTimes)
                continue;

            while (m_CurUpdateTimes < curUpdateTimes)
            {
                m_CurUpdateTimes++;

                lock (m_ToAddLifeCycles)
                {
                    if (m_ToAddLifeCycles.Count > 0)
                    {
                        foreach (var gameLifeCycle in m_ToAddLifeCycles)
                        {
                            m_GameLifeCycles.Add(gameLifeCycle);
                        }
                        m_ToAddLifeCycles.Clear();
                    }
                }

                lock (m_ToRemoveLifeCycles)
                {
                    if (m_ToRemoveLifeCycles.Count > 0)
                    {
                        foreach (var gameLifeCycle in m_ToRemoveLifeCycles)
                        {
                            m_GameLifeCycles.Remove(gameLifeCycle);
                        }
                        m_ToRemoveLifeCycles.Clear();
                    }
                }

                for (int i = 0; i < m_GameLifeCycles.Count;)
                {
                    if (m_GameLifeCycles[i] != null)
                    {
                        m_GameLifeCycles[i].Update(m_CurUpdateTimes);
                        i++;
                    }
                    else
                    {
                        m_GameLifeCycles.RemoveAt(i);
                    }
                }

                _Update();

                Thread.Sleep(5);
            }
        }


    }

    protected virtual void _Update()
    {

    }

}

